/*
	Copyright (C) 2004-2005 Cory Nelson

	This software is provided 'as-is', without any express or implied
	warranty.  In no event will the authors be held liable for any damages
	arising from the use of this software.

	Permission is granted to anyone to use this software for any purpose,
	including commercial applications, and to alter it and redistribute it
	freely, subject to the following restrictions:

	1. The origin of this software must not be misrepresented; you must not
		claim that you wrote the original software. If you use this software
		in a product, an acknowledgment in the product documentation would be
		appreciated but is not required.
	2. Altered source versions must be plainly marked as such, and must not be
		misrepresented as being the original software.
	3. This notice may not be removed or altered from any source distribution.
	
	CVS Info :
		$Author: phrostbyte $
		$Date: 2005/06/16 20:46:40 $
		$Revision: 1.1 $
*/
#include "sqlite3\\sqlite3Ex.h"
#include "sqlite3x.hpp"

extern PFN_Sqlite3_Prepare      g_pfnsqlite3_prepare;
extern PFN_Sqlite3_column_count g_pfnsqlite3_column_count;
extern PFN_Sqlite3_Prepare16    g_pfnsqlite3_prepare16;
extern PFN_Sqlite3_Finalize     g_pfnsqlite3_finalize;
extern PFN_Sqlite3_bind_null    g_pfnsqlite3_bind_null;
extern PFN_Sqlite3_bind_int     g_pfnsqlite3_bind_int;
extern PFN_Sqlite3_bind_int64   g_pfnsqlite3_bind_int64;
extern PFN_Sqlite3_bind_double  g_pfnsqlite3_bind_double;
extern PFN_Sqlite3_bind_text    g_pfnsqlite3_bind_text;
extern PFN_Sqlite3_bind_text16  g_pfnsqlite3_bind_text16;
extern PFN_Sqlite3_bind_blob    g_pfnsqlite3_bind_blob;
namespace sqlite3x {

sqlite3_command::sqlite3_command( sqlite3_connection &con, const char *sql ) : con( con ),refs( 0 )
{
	const char *tail = NULL;
	int iRet = g_pfnsqlite3_prepare( con.m_pDBConn, sql, -1, &stmt, &tail ) ;
	if (  iRet!= SQLITE_OK )
	{
		throw database_error( con );
	}

	m_nArgc = g_pfnsqlite3_column_count( stmt );
}

sqlite3_command::sqlite3_command( sqlite3_connection &con, const wchar_t *sql ) : con( con ),refs( 0 ) {
	const wchar_t *tail=NULL;
	int iRet = g_pfnsqlite3_prepare16( con.m_pDBConn, sql, -1, &stmt, (const void**)&tail );
	if ( iRet != SQLITE_OK )
		throw database_error( con );

	m_nArgc= g_pfnsqlite3_column_count(stmt);

}

sqlite3_command::sqlite3_command( sqlite3_connection &con, const string &sql ) : con( con ),refs( 0 ) {
	const char *tail=NULL;
	int iRet =  g_pfnsqlite3_prepare( con.m_pDBConn, sql.data(), (int)sql.length(), &stmt, &tail ) ;
	if(iRet != SQLITE_OK )
		throw database_error( con );

	m_nArgc = g_pfnsqlite3_column_count( stmt );
}

sqlite3_command::sqlite3_command(sqlite3_connection &con, const wstring &sql) : con(con),refs(0) {
	const wchar_t *tail=NULL;
	int iRet = g_pfnsqlite3_prepare16(con.m_pDBConn, sql.data(), (int)sql.length()*2, &stmt, (const void**)&tail) ;
	if( iRet!=SQLITE_OK)
		throw database_error(con);

	m_nArgc=g_pfnsqlite3_column_count(stmt);
}

sqlite3_command::~sqlite3_command() {
	g_pfnsqlite3_finalize(stmt);
}

void sqlite3_command::bind(int index) {
	if(g_pfnsqlite3_bind_null(stmt, index)!=SQLITE_OK)
		throw database_error(con);
}

void sqlite3_command::bind(int index, int data) {
	if(g_pfnsqlite3_bind_int(stmt, index, data)!=SQLITE_OK)
		throw database_error(con);
}

void sqlite3_command::bind(int index, long long data) {
	if(g_pfnsqlite3_bind_int64(stmt, index, data)!=SQLITE_OK)
		throw database_error(con);
}

void sqlite3_command::bind(int index, double data) {
	if(g_pfnsqlite3_bind_double(stmt, index, data)!=SQLITE_OK)
		throw database_error(con);
}

void sqlite3_command::bind(int index, const char *data, int datalen) {
	if(g_pfnsqlite3_bind_text(stmt, index, data, datalen, SQLITE_TRANSIENT)!=SQLITE_OK)
		throw database_error(con);
}

void sqlite3_command::bind(int index, const wchar_t *data, int datalen) {
	if(g_pfnsqlite3_bind_text16(stmt, index, data, datalen, SQLITE_TRANSIENT)!=SQLITE_OK)
		throw database_error(con);
}

void sqlite3_command::bind(int index, const void *data, int datalen) {
	if(g_pfnsqlite3_bind_blob(stmt, index, data, datalen, SQLITE_TRANSIENT)!=SQLITE_OK)
		throw database_error(con);
}

void sqlite3_command::bind(int index, const string &data) {
	if(g_pfnsqlite3_bind_text(stmt, index, data.data(), (int)data.length(), SQLITE_TRANSIENT)!=SQLITE_OK)
		throw database_error(con);
}

void sqlite3_command::bind(int index, const wstring &data) {
	if(g_pfnsqlite3_bind_text16(stmt, index, data.data(), (int)data.length()*2, SQLITE_TRANSIENT)!=SQLITE_OK)
		throw database_error(con);
}

sqlite3_reader sqlite3_command::executereader()
{
	return sqlite3_reader(this);
}

void sqlite3_command::executenonquery() {
	executereader().read();
}

int sqlite3_command::executeint() {
	sqlite3_reader reader=executereader();
	if(!reader.read()) throw database_error("nothing to read");
	return reader.getint(0);
}

long long sqlite3_command::executeint64() {
	sqlite3_reader reader=executereader();
	if(!reader.read()) throw database_error("nothing to read");
	return reader.getint64(0);
}

double sqlite3_command::executedouble() {
	sqlite3_reader reader=executereader();
	if(!reader.read()) throw database_error("nothing to read");
	return reader.getdouble(0);
}

string sqlite3_command::executestring() {
	sqlite3_reader reader=executereader();
	if(!reader.read()) throw database_error("nothing to read");
	return reader.getstring(0);
}

wstring sqlite3_command::executestring16() {
	sqlite3_reader reader=executereader();
	if(!reader.read()) throw database_error("nothing to read");
	return reader.getstring16(0);
}

string sqlite3_command::executeblob() {
	sqlite3_reader reader=executereader();
	if(!reader.read()) throw database_error("nothing to read");
	return reader.getblob(0);
}

}
